package girvate;

import frameWork.entity.TestDrawNode;
import frameWork.util.Vector2D;

import java.awt.*;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.util.ArrayList;

public class GrivateNode extends TestDrawNode{
    Point2D v;
    double r;
    double mass;

    public GrivateNode(Point p){
        super(p);
        double size=(Math.random()*Math.random()*55+7);
        r=size/2;
        mass=Math.PI*r*r/100;
//        area.add( new Area( new Rectangle(0,0,size,size)));
        area.add(new Area(new Arc2D.Double(-size/2,-size/2,size,size,0.0,360,Arc2D.CHORD)));
        color=new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256));
        Point2D to=Vector2D.jian(target,p);
        to=Vector2D.resize(to,3.0);
        v=new Point2D.Double(to.getY(),-to.getX());
        //v=new Point2D.Double(0,0);
        //double tt=0.5;
        //v=Vector2D.jia(v,new Point2D.Double(Math.random()*tt*2-tt,Math.random()*tt*2-tt));
    }
    static public ArrayList<GrivateNode> arr;

    @Override
    public void run() {
        super.run();
        move();
    }


    public void move(){
        for (GrivateNode n : arr) {
            deal(n);
        }
        cen = Vector2D.jia(cen, v);
        for(GrivateNode n: arr){
            onIntersecting(n);
        }
        go();
    }


    public void deal(GrivateNode g){
        Point2D to= Vector2D.jian(g.cen,cen);
        double len=Vector2D.len(to);
        if(len==0)return ;
        double li=1/len/len;
        Point2D f=Vector2D.resize(to,Math.min(li,1000));
        f=Vector2D.mulit(f,mass*g.mass);

        //撞击预判
//        Point2D temp=Vector2D.jia(v,f);
//        len=Vector2D.len(Vector2D.jian(g.position,Vector2D.jia(position,temp)));
        if(len<=r+g.r){
            onCollide(g);
        }
//        else v= Vector2D.jia(v,f);
//        v=Vector2D.jia(v,new Point2D.Double(0,0.0001));
//        else v=temp;
//
    }

    static int Boundx=1920,Boundy=1050;
    public void bound(){
        if(cen.getX()<r){
            v.setLocation(-v.getX(),v.getY());
            cen.setLocation(r*2-cen.getX(),cen.getY());
        }
        if(cen.getY()<r){
            v.setLocation(v.getX(),-v.getY());
            cen.setLocation(cen.getX(),2*r-cen.getY());
        }
        if(cen.getX()>Boundx-r){
            v.setLocation(-v.getX(),v.getY());
            cen.setLocation(Boundx-(r*2+cen.getX()-Boundx),cen.getY());
        }
        if(cen.getY()>Boundy-r){
            //v.setLocation(v.getX()*0.9,-v.getY()*0.9);//地板
            v.setLocation(v.getX(),-v.getY());
            cen.setLocation(cen.getX(),Boundy-(2*r+cen.getY()-Boundy));
        }
    }
/**
 *  刚体碰撞公式
 *  https://introcs.cs.princeton.edu/java/assignments/collisions.html
 */
    public void onCollide(GrivateNode g){
//        Point2D a=Vector2D.mulit(v,(mass-g.mass));
//        Point2D b=Vector2D.mulit(g.v,2*g.mass);
//        v=Vector2D.resize(Vector2D.jia(a,b),1/(mass+g.mass));

        double len=g.r+r;len*=len;
        double k=mass+g.mass;
        k=2*g.mass/(len*k);
        k*=Vector2D.point(Vector2D.jian(cen,g.cen),Vector2D.jian(v,g.v));
        v=Vector2D.jian(v,Vector2D.mulit(Vector2D.resize(Vector2D.jian(cen,g.cen),(r+g.r)),k));
        v=Vector2D.jian(v,Vector2D.resize(Vector2D.jian(cen,g.cen),k));
    }

    public void go() {
        //Vector2D.resize(v,Vector2D.len(v)*0.9);
        cen = Vector2D.jia(cen, v);
        position = new Point((int) cen.getX(), (int) cen.getY());

        bound();
    }
    public void onIntersecting(GrivateNode g){
        Point2D to= Vector2D.jian(g.cen,cen);
        double len=Vector2D.len(to);
        if(len<=r+g.r){
            double mov=(r+g.r-len)/2;
            to=Vector2D.resize(to,mov);
            cen=Vector2D.jian(cen,to);
            g.cen=Vector2D.jia(g.cen,to);
        }
    }



    static Point2D target=new Point2D.Double(1920/2,1080/2);
    Point2D cen=new Point2D.Double(position.x, position.y);

//    public void deal(){
//        int tt=36;
//        for(int i=0;i<tt;i++){
//            double r=i*1.0/tt*Math.PI*2;
//            double size=0.2;
//            double x=(Math.sin(r)*target.getX()*size+target.getX());
//            double y=(Math.cos(r)*target.getY()*size+target.getY());
//            Point2D p= new Point2D.Double(target.getX()+x,target.getY()+y);
//            deal2(p,0.2);
//        }
//    }
//    public void deal2(Point2D target,double fval){

}
